﻿using Microsoft.AspNetCore.DataProtection.KeyManagement;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using SharedKernel.Infrastructure.Redis;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SharedKernel.Infrastructure.Caches
{
    /// <summary>
    /// 缓存工厂
    /// </summary>
    public class CacheServiceFactory : ICacheService
    {
        /// <summary>
        /// 具体的缓存接口（redis、内存）
        /// </summary>
        private readonly ICacheService _innerCache;

        public CacheServiceFactory(IMemoryCache memoryCache, IOptions<RedisOptions> redisOptions, IServiceProvider serviceProvider)
        {
            // 优先尝试初始化 Redis 缓存
            try
            {
                var redisService = serviceProvider.GetService<RedisCacheService>();
                if (redisService == null || !redisService.IsOpen())
                {
                    throw new ArgumentNullException("获取Redis缓存失败");
                }
                _innerCache = redisService;
            }
            catch (Exception ex)
            {
                // Redis 初始化失败时，降级为内存缓存
                _innerCache = new MemoryCacheService(memoryCache);
                Console.WriteLine($"{ex.Message}自动回退到内存缓存。请注意：内存缓存不支持分布式");
            }
        }


        #region 直接调用具体的缓存实现
        public Task<T?> GetAsync<T>(string key) => _innerCache.GetAsync<T>(key);
        public Task<bool> SetAsync<T>(string key, T value, TimeSpan? expiration = null) => _innerCache.SetAsync(key, value, expiration);
        public Task<bool> RemoveAsync(string key) => _innerCache.RemoveAsync(key);
        public Task<bool> ExistsAsync(string key) => _innerCache.ExistsAsync(key);
        public void ChangeDataBase(int db) => _innerCache.ChangeDataBase(db);


        public T? Get<T>(string key) => _innerCache.Get<T>(key);
        public bool Set<T>(string key, T value, TimeSpan? expiration = null) => _innerCache.Set(key, value, expiration);
        public bool Remove(string key) => _innerCache.Remove(key);
        public bool Exists(string key) => _innerCache.Exists(key);
        #endregion

    }
}
